//
//  SHUnitView.swift
//  SHUnitView
//
//  Created by 石虎 on 2020/9/22.
//  Copyright © 2020 石虎. All rights reserved.
//

import UIKit

public class SHUnitView: UIView {
    
    // willSet: 会在该值被储存之前被调用
    // didSet : 会在一个新值被储存后被调用
    
    /// 上下左右的边距,默认 0
    public var contentEdge = UIEdgeInsets.zero {
        didSet {
            recalculateEachItemWidth()
        }
    }
    
    /// unit 之间的间距,默认 0
    public var spacing: CGFloat = 0 {
        didSet {
            recalculateEachItemWidth()
        }
    }
    
    /// 默认一行几个 item,默认 3
    public var countOfColumn: Int = 3 {
        didSet {
            recalculateEachItemWidth()
        }
    }
    
    /// item 高宽比.默认 1, 高/宽的值
    public var aspectRatio: CGFloat = 1 {
        didSet {
            recalculateEachItemWidth()
        }
    }
    
    // MARK:- 私有属性
    
    //这种写法没有对”读”做限制,相当于使用了默认的 internal 权限。
    public fileprivate(set) var arrangedSubViews = [UIView]() // 所有的子 view
    
    // 当前高度
    public fileprivate(set) var estimatedHeight: CGFloat = 10
    
    
    // MARK:- 布局使用
    
    // 是否移除视图
    fileprivate var isRemoveViews: Bool = false
    
    // 最后一次添加的 views ,从 index 开始
    fileprivate var lastAddRange: Range = 0 ..< 0
    
    // contentEdge \ spacing \ countOfColumn 变化都会更新
    fileprivate var eachWidth: CGFloat = 0
    
    // 是否需要从新布局
    fileprivate var isNeedReLayout = false
    
    
    
}

// MARK:- 添加移除子View

extension SHUnitView {
    
    /// 添加多个数组中的视图
    public func addArrangedSubview(_ view: UIView) {
        addArrangedSubview([view])
    }
    
    public func addArrangedSubview(_ views: [UIView]) {
        
        let beginCount = arrangedSubViews.count - 1 < 0 ? 0 : arrangedSubViews.count - 1
        arrangedSubViews.append(contentsOf: views)
        let endCount = arrangedSubViews.count
        lastAddRange = beginCount ..< endCount
        for view in views {
            addSubview(view)
        }
        //添加完成再一次更新布局
        isNeedReLayout = true
        setNeedsUpdateConstraints()
    }
    
    /// 删除多个数组中的视图
    public func removeArrangedSubview(_ view: UIView) {
        removeArrangedSubviews([view])
    }
    
    public func removeArrangedSubviews(_ views: [UIView]) {
        
        for view in views {
            if let index = arrangedSubViews.firstIndex(of: view) {
                arrangedSubViews.remove(at: index)
            }
            view.removeFromSuperview()
        }
        // 只要不为空就可以
        isRemoveViews = true
        // 移除完毕之后再允许更改
        isNeedReLayout = true
        //setNeedsUpdateConstraints 保证之后肯定会调用 updateConstraintsIfNeeded .系统然后会调用 updateConstraints，. 以解决这个由属性改变带来的影响。
        //SetNeedsLayout 保证之后肯定会调用 layoutIfNeeded .
        setNeedsUpdateConstraints()
    }
    
}

// MARK:- 更新布局

extension SHUnitView {
    
    public override func layoutSubviews() {
        super.layoutSubviews()
        if frame.width > 0 && eachWidth == 0 {
            recalculateEachItemWidth() // 计算宽度
        }
    }
    
    public override func updateConstraints() {
        if frame.width > 0 && isNeedReLayout {
            updateUnitViewConstraints()
        }
        super.updateConstraints()
    }
    
    /// 更新变动的 view 和 父类 view 的高度
    fileprivate func updateUnitViewConstraints() {
        
        if frame.width == 0 { return }
        if arrangedSubViews.count == 0 && isRemoveViews == false { return }
        isNeedReLayout = false
        
        // 如果是移除 view,则更新高度
        if isRemoveViews == true {
            
            updateUnitViewHeightConstraints()
            // 删除置空
            isRemoveViews = false
            return
        }
       
        // 添加的是空的,不进行添加 
        if lastAddRange.isEmpty { return }
        // 添加 有的view
        let addViews = arrangedSubViews[lastAddRange.startIndex ..< lastAddRange.endIndex ]
        
        if addViews.count == 0 { return }
        
        //enumerated() :这个函数会返回一个新的序列，包含了初始序列里的所有元素，以及与元素相对应的编号。
        for (index,view) in addViews.enumerated() {
            // 计算 index
            let calculateIndex = lastAddRange.startIndex + index
            let frame = calculateLocation(from: calculateIndex, width: eachWidth)
            
            let top = frame.0
            let left = frame.1
            
            view.snp.remakeConstraints { (make) in
                make.width.equalTo(eachWidth)
                make.height.equalTo(view.snp.width).multipliedBy(aspectRatio)
                make.top.equalTo(top)
                make.left.equalTo(left)
            }
        }
        
        // 置空
        lastAddRange = 0..<0
        updateUnitViewHeightConstraints()
    }
    
    /// 更新高度
    fileprivate func updateUnitViewHeightConstraints() {
        
        var finalcolumn = arrangedSubViews.count / countOfColumn
        if arrangedSubViews.count % countOfColumn > 0 {
            finalcolumn += 1
        }
        let height = (CGFloat(finalcolumn)) * ((eachWidth * aspectRatio) + spacing) + contentEdge.top + contentEdge.bottom - spacing
        if estimatedHeight != height {
            estimatedHeight = height
            snp.updateConstraints { (make) in
                make.height.equalTo(estimatedHeight)
            }
        }
    }
    
    /// 计算每个item的宽度
    func recalculateEachItemWidth() {
        
        if frame.width == 0 { return }
        let mewWidth = (frame.width - contentEdge.left - contentEdge.right - ((CGFloat(countOfColumn) - 1) * spacing)) / CGFloat(countOfColumn)
        if eachWidth != mewWidth && mewWidth > 0 {
            eachWidth = mewWidth
            // 需要重新布局所有的子 view
            lastAddRange = 0 ..< arrangedSubViews.count
            isNeedReLayout = true
            setNeedsUpdateConstraints()
        }
    }
    
    /// 计算位置
    /// - Parameter index: 第几个
    /// return (top,left)
    fileprivate func calculateLocation(from index: Int,width: CGFloat) -> (CGFloat, CGFloat) {
        
        // 当前行数
        let row = CGFloat(index / countOfColumn)
        // 当前列数
        let column = CGFloat(index % countOfColumn)
        let top = contentEdge.top + row * (eachWidth * aspectRatio) + spacing
        let left = contentEdge.left + column * (eachWidth + spacing)
        return (top,left)
    }
}



// MARK: - Private method

extension SHUnitView {
    
}

// MARK: - Delegate

extension SHUnitView {
    
}
